package com.sondertara.joya.pool.datasource;


import com.sondertara.joya.pool.config.DataSourceConfig;
import com.sondertara.joya.pool.connection.ConnectionPool;
import lombok.extern.slf4j.Slf4j;
import org.jspecify.annotations.NonNull;

import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.Properties;
import java.util.logging.Logger;

/**
 * zh 构建连接池示例模板
 *
 * @author: ZhangHe
 * @since: 2020/10/31 13:50
 */
@Slf4j
public class JoyaDataSource extends DataSourceConfig implements DataSourceAdapter, DataSource, AutoCloseable {

    @NonNull
    private String driverClassName;
    @NonNull
    private String username;
    @NonNull
    private String password;
    @NonNull
    private String jdbcUrl;

    private Properties properties;

    public String getDriverClassName() {
        return driverClassName;
    }

    public void setDriverClassName(String driverClassName) {
        this.driverClassName = driverClassName;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getJdbcUrl() {
        return jdbcUrl;
    }

    public void setJdbcUrl(String jdbcUrl) {
        this.jdbcUrl = jdbcUrl;
    }

    public Properties getProperties() {
        return properties;
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

    private volatile ConnectionPool<Connection> connectionPool;

    @Override
    public Connection getConnectionObject() throws SQLException {
        try {
            if (connectionPool == null) {
                synchronized (this) {
                    if (connectionPool == null) {
                        createDefaultConnectionPool();
                    }
                }
            }
            return connectionPool.getConnectionObject();
        } catch (SQLException e) {
            throw e;
        } catch (Exception e) {
            log.error("额外的获取连接异常", e);
            throw new SQLException(e);
        }
    }

    private void createDefaultConnectionPool() {
        this.connectionPool = new SimpleSqlPool(this);
    }

    @Override
    public Connection getConnection() throws SQLException {
        return getConnectionObject();
    }


    @Override
    @SuppressWarnings("unchecked")
    public <T> T unwrap(Class<T> iface) throws SQLException {
        if (iface.isInstance(this)) {
            return (T)this;
        } else {
            throw new SQLException("DataSource of type [" + this.getClass().getName() + "] cannot be unwrapped as [" + iface.getName() + "]");
        }
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return iface.isInstance(this);
    }

    @Override
    public PrintWriter getLogWriter() throws SQLException {
        throw new SQLFeatureNotSupportedException();
    }

    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {
        throw new SQLFeatureNotSupportedException();
    }

    @Override
    public void setLoginTimeout(int seconds) throws SQLException {
        DriverManager.setLoginTimeout(seconds);
    }

    @Override
    public int getLoginTimeout() throws SQLException {
        return DriverManager.getLoginTimeout();
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        throw new SQLFeatureNotSupportedException();
    }

    @Override
    public void close() throws Exception {
        connectionPool.close();
    }
}
